#include <memory>
#include <string>
#include <iostream>

using namespace std;

int main()
{
    unique_ptr<double> p1; // 可以指向一个 double 的 unique_ptr
    unique_ptr<int> p2(new int(42)); // p2 指向一个值为 42 的 int

    unique_ptr<string> p3(new string("Stegosaurus"));
    // unique_ptr<string> p4(p3);      // 错误：unique_ptr 不支持拷贝
    unique_ptr<string> p4;
    // p4 = p3;                        // 错误：unique_ptr 不支持赋值

    // 将所有权从 p3（指向 string Stegosaurus）转移给 p5
    unique_ptr<string> p5(p3.release()); // release 将 p3 置为空
    unique_ptr<string> p6(new string("Trex"));

    cout << "after p3 release *p5: " << *p5 << endl;

    // 将所有权从 p6 转移给 p5
    p5.reset(p6.release()); // reset 释放了 p6 原来指向的内存

    cout << "after p6 release *p5: " << *p5 << endl;

    // p5.release();           // 错误：p5 不会释放内存，而且我们丢失了指针
    auto p = p5.release();  // 正确，但我们必须记得 delete(p)
    delete(p);

    // p 指向一个类型为 objT 的对象，并使用一个类型为 delT 的对象释放 objT 对象
    // 它会调用一个名为 fcn 的 delT 类型对象
    // unique_ptr<objT, delT> p(new objT, fcn);
}

unique_ptr<int> clone(int p)
{
    // 正确：从 int* 创建一个 unique_ptr<int>
    return unique_ptr<int>(new int(p));
}

// unique_ptr<int> clone(int p) {
//     // 正确：返回一个局部对象的拷贝
//     unique_ptr<int> ret(new int(p));
//     // ...
//     return ret;
// }

struct destination;                 // 表示我们正在连接什么
struct connection;                  // 使用连接所需的信息
connection connect(destination*);   // 打开连接
void disconnect(connection);        // 关闭给定的连接
void f(destination &d /* 其他参数 */)
{
    // connection c = connect(&d);
    // 当 p 被销毁时，它不会对自己保存的指针执行 delete，而是调用 disconnect
    // unique_ptr<connection, decltype(disconnect)*> p(&c, disconnect);
    // 使用连接
    // 当 f 退出时（即使是由于异常而退出），connection 会被正确关闭
}